package org.wheel.jpa.provider;

import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl;
import org.hibernate.jpa.boot.internal.PersistenceUnitInfoDescriptor;
import org.springframework.context.annotation.DependsOn;
import org.springframework.orm.jpa.persistenceunit.SmartPersistenceUnitInfo;
import org.wheel.jpa.factory.MultableSessionFactory;

import javax.persistence.EntityManagerFactory;
import javax.persistence.spi.PersistenceUnitInfo;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Aspect
@DependsOn(value = { "jpaVendorAdapter" })
public class JpaHibernatePersistenceProvider extends HibernatePersistenceProvider {

    @Around("execution(* org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter.getPersistenceProvider())")
    public Object doAround() {
        return this;
    }

    @Override
    public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info, Map properties) {
        List<String> mergedClassesAndPackages = new ArrayList<>(info.getManagedClassNames());
        if (info instanceof SmartPersistenceUnitInfo) {
            mergedClassesAndPackages.addAll(((SmartPersistenceUnitInfo) info).getManagedPackages());
        }
        PersistenceUnitInfoDescriptor descriptor = new PersistenceUnitInfoDescriptor(info){
            @Override
            public List<String> getManagedClassNames() {
                return mergedClassesAndPackages;
            }
        };
        return new MultableSessionFactory(() -> new EntityManagerFactoryBuilderImpl(descriptor, properties));
    }

}
